package com.ylkj.patient.utils;

import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.view.KeyEvent;
import android.widget.ProgressBar;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.core.content.FileProvider;

import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.yilijk.base.utils.ALog;
import com.ylkj.patient.dialog.AlertDialog;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class UpgradeManager {

    /**
     * 下载中
     */
    private static final int DOWNLOAD = 1;

    /**
     * 下载结束
     */
    private static final int DOWNLOAD_FINISH = 2;

    /**
     * 显示错误消息
     */
    private static final int ERROR = 9;
    //增加下载异常容错
    private static final int ABNORMAL = 10;
    private String mUpdateContext = "检测到新版本，请立即更新！";
    private boolean mIsFouse = false;

    /**
     * 服务端版本号
     */
    private int mServerVersion;

    /**
     * 下载URL
     */
    private String mDownloadUrl;

    /**
     * 下载保存路径
     */
    private String mSavePath;

    /**
     * 记录进度条数值
     */
    private int progress;

    private MaterialDialog mProgressDialog;

    private Context mContext;

    private UpdateFlag updateFlag;

    /**
     * 是否取消更新
     */
    private boolean cancelUpdate = false;

    /**
     * 错误消息
     */
    private String errorMessage;

    private UpgradeManagerListener listener;

    @SuppressLint("HandlerLeak")
    private Handler mHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case DOWNLOAD:
                    // 设置进度条位置
                    if (mProgressDialog != null) {
                        mProgressDialog.setMaxProgress(msg.arg1);
                        mProgressDialog.setProgress(msg.arg2);
                    }
                    break;
                case DOWNLOAD_FINISH:
                    // 安装文件
                    if (mProgressDialog != null) {
                        mProgressDialog.dismiss();
                    }
                    installApk();
                    break;
                case ERROR:
                    mProgressDialog.dismiss();
                    checkUpdate();
                    if (errorMessage != null && errorMessage.length() > 0) {
                        Toast.makeText(mContext, errorMessage, Toast.LENGTH_SHORT).show();
                    }
                case ABNORMAL:
                    mProgressDialog.dismiss();
                    if (errorMessage != null && errorMessage.length() > 0) {
                        Toast.makeText(mContext, errorMessage, Toast.LENGTH_SHORT).show();
                    }
                default:
                    break;
            }
        }

    };

    /**
     * @param context
     * @param mSavePath
     * @param version
     * @param downloadUrl
     * @param updateFlag    更新标志
     * @param isFouse       是否强更
     * @param updateContext
     */
    public UpgradeManager(Context context, String mSavePath, int version, String downloadUrl, UpdateFlag updateFlag, boolean isFouse, String updateContext) {
        this.mContext = context;
        this.mSavePath = mSavePath;
        this.mServerVersion = version;
        this.mDownloadUrl = downloadUrl;
        this.mIsFouse = isFouse;
        this.updateFlag = updateFlag;
        this.mUpdateContext = updateContext;
    }


    /**
     * 检测软件更新
     */
    public void checkUpdate() {
        if (!isUpdate()) {//版本号低于当前版本，不更新
            if (listener != null) {
                listener.onUpgradeDismiss();
            }
            return;
        }

        updateVersionOne();
    }

    /**
     * 检查软件是否有更新版本
     *
     * @return 软件是否有更新版本
     */
    private boolean isUpdate() {
        int versionCode = getVersionName(this.mContext);
        ALog.d("LAE", versionCode + "-----" + mServerVersion);
        return versionCode < mServerVersion ? true : false;
    }

    /**
     * 获取客户端版本号
     *
     * @return 客户端版本号
     */
    private int getVersionName(Context context) {
        int versionName = 0;
        try {
            versionName = context.getPackageManager().getPackageInfo("com.ylkj.patient", 0).versionCode;
        } catch (NameNotFoundException ignored) {
        }
        return versionName;
    }

    /**
     * 版本更新确认
     *
     * @param
     */
    public void updateVersionOne() {
        final AlertDialog mAlertDialog = new AlertDialog(mContext);
        if (mIsFouse) {
            mAlertDialog.setOnKeyListener(mKeyDialogListener);
        }
        mAlertDialog.setMessageText(mUpdateContext);
        mAlertDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
            @Override
            public void onDismiss(DialogInterface dialogInterface) {
                if (!mIsFouse && listener != null) {
                    listener.onUpgradeDismiss();
                }
            }
        });
        mAlertDialog.setCanceledOnTouchOutside(!mIsFouse);
        mAlertDialog.setCancelable(!mIsFouse);
        mAlertDialog.setOnDialogListener(new AlertDialog.OnDialogListener() {
            @Override
            public boolean onPositiveButton() {
                switch (updateFlag) {
                    case UPDATE_FLAG_HUAWEI: {
                        AppMarketUtil.getInstance().callHuaweiAppDetail(mContext.getPackageName(), mContext, new AppMarketUtil.JumpListener() {
                            @Override
                            public void onThrowable(Throwable throwable) {
                                showDownloadDialog();
                                try {
                                    if (mAlertDialog != null && mAlertDialog.isShowing()) {
                                        mAlertDialog.dismiss();
                                    }
                                } catch (Throwable throwable1) {
                                    throwable1.printStackTrace();
                                }
                            }
                        });
                        break;
                    }
                    case UPDATE_FLAG_XIAOMI: {
                        AppMarketUtil.getInstance().callXiaomiAppDetail(mContext.getPackageName(), mContext, new AppMarketUtil.JumpListener() {
                            @Override
                            public void onThrowable(Throwable throwable) {
                                showDownloadDialog();
                                try {
                                    if (mAlertDialog != null && mAlertDialog.isShowing()) {
                                        mAlertDialog.dismiss();
                                    }
                                } catch (Throwable throwable1) {
                                    throwable1.printStackTrace();
                                }
                            }
                        });
                        break;
                    }
                    case UPDATE_FLAG_OPPO: {
                        AppMarketUtil.getInstance().callOppoAppDetail(mContext.getPackageName(), mContext, new AppMarketUtil.JumpListener() {
                            @Override
                            public void onThrowable(Throwable throwable) {
                                showDownloadDialog();
                                try {
                                    if (mAlertDialog != null && mAlertDialog.isShowing()) {
                                        mAlertDialog.dismiss();
                                    }
                                } catch (Throwable throwable1) {
                                    throwable1.printStackTrace();
                                }
                            }
                        });
                        break;
                    }
                    case UPDATE_FLAG_VIVO: {
                        AppMarketUtil.getInstance().callVivoAppDetail(mContext.getPackageName(), mContext, new AppMarketUtil.JumpListener() {
                            @Override
                            public void onThrowable(Throwable throwable) {
                                showDownloadDialog();
                                try {
                                    if (mAlertDialog != null && mAlertDialog.isShowing()) {
                                        mAlertDialog.dismiss();
                                    }
                                } catch (Throwable throwable1) {
                                    throwable1.printStackTrace();
                                }
                            }
                        });
                        break;
                    }
                    default: {
                        showDownloadDialog();
                        return true;
                    }
                }
                return false;
            }

            @Override
            public void onNegativeButton() {
                if (mIsFouse) {
                    mAlertDialog.dismiss();
                    android.os.Process.killProcess(android.os.Process.myPid());    //获取PID
                    System.exit(0);   //常规java、c#的标准退出法，返回值为0代表正常退出
                } else {
                }
            }

        });
        if (mIsFouse) {
            mAlertDialog.setNegativeText("退出");
        } else {
            mAlertDialog.setNegativeText("取消");
        }
        mAlertDialog.show();
    }

    public DialogInterface.OnKeyListener mKeyDialogListener = new DialogInterface.OnKeyListener() {
        public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
                return true;
            } else {
                return false;
            }
        }
    };

    /**
     * 显示软件下载对话框
     */
    private void showDownloadDialog() {
        if (this.mIsFouse) {
            mProgressDialog = new MaterialDialog.Builder(mContext)
                    .title("正在更新")
                    .progress(false, 0, true)
                    .progressNumberFormat("%d/%d kb")
                    .widgetColor(Color.parseColor("#3c84d0"))
                    .cancelable(false)
                    .canceledOnTouchOutside(false)
                    .onNegative(new MaterialDialog.SingleButtonCallback() {
                        @Override
                        public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                            cancelUpdate = true;
                            mProgressDialog.dismiss();
                        }
                    })
                    .show();
            // 下载安装包
            downloadApk();
        } else {
            mProgressDialog = new MaterialDialog.Builder(mContext)
                    .title("正在更新")
                    .progress(false, 0, true)
                    .negativeText("取消")
                    .progressNumberFormat("%d/%d kb")
                    .widgetColor(Color.parseColor("#3c84d0"))
                    .onNegative(new MaterialDialog.SingleButtonCallback() {
                        @Override
                        public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                            cancelUpdate = true;
                            mProgressDialog.dismiss();
                        }
                    })
                    .show();
            // 下载安装包
            downloadApk();
        }
    }

    /**
     * 下载apk文件
     */
    private void downloadApk() {
        // 启动新线程下载软件
        new DownloadApkThread().start();
    }

    public void setListener(UpgradeManagerListener listener) {
        this.listener = listener;
    }

    /**
     * 下载文件线程
     */
    private class DownloadApkThread extends Thread {
        @Override
        public void run() {
            InputStream is = null;
            FileOutputStream fos = null;
            try {


                // 判断SD卡是否存在，并且是否具有读写权限
                if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                    ALog.d("chen", "apk包下载路径为" + mSavePath);
                    URL url = new URL(mDownloadUrl);
                    // 创建连接
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setConnectTimeout(600000);
                    boolean useHttps = mDownloadUrl.startsWith("https");
                    if (useHttps) {
                        HttpsURLConnection https = (HttpsURLConnection) conn;
                        trustAllHosts(https);
                        https.setHostnameVerifier(DO_NOT_VERIFY);
                    }
                    conn.connect();
                    // 获取文件大小
                    int length = conn.getContentLength();
                    // 创建输入流
                    is = conn.getInputStream();
                    int idx = mDownloadUrl.lastIndexOf("/");
                    String name = mDownloadUrl.substring(idx + 1);
                    File file = getFile();

                    fos = new FileOutputStream(file);
                    int count = 0;
                    // 缓存
                    byte buf[] = new byte[2048];
                    int len;
                    // 写入到文件中
                    //增加下载容错
                    int downloadType = 0;
                    int lastProgress = 0;
                    while (!cancelUpdate && (len = is.read(buf)) > 0) {
                        fos.write(buf, 0, len);
                        count += len;
                        // 计算进度条位置
                        progress = (int) (((float) count / length) * 100);
                        if (progress != lastProgress) {
                            lastProgress = progress;
                            downloadType = 0;
                        } else {
                            downloadType++;
                            if (downloadType == 2048) {
                                fos.flush();
                                errorMessage = "下载异常！请重试";
                                mHandler.sendEmptyMessage(ABNORMAL);
                                return;
                            }
                        }
                        lastProgress = progress;
                        // 更新进度
                        Message msg = mHandler.obtainMessage(DOWNLOAD);
                        msg.arg1 = length / 1024;
                        msg.arg2 = count / 1024;
                        msg.sendToTarget();
                    }
                    if (!cancelUpdate) {
                        // 下载完成
                        conn.disconnect();
                        mHandler.sendEmptyMessage(DOWNLOAD_FINISH);
                    }
                }
            } catch (MalformedURLException e) {
                ALog.e("chen", e.toString());
                e.printStackTrace();
                errorMessage = "下载地址不正确";
                mHandler.sendEmptyMessage(ERROR);
            } catch (IOException e) {
                e.printStackTrace();
                errorMessage = "下载失败！" + e;
                mHandler.sendEmptyMessage(ERROR);
            } finally {
                if (is != null) {
                    try {
                        is.close();
                    } catch (IOException ignored) {
                    }
                }
                if (fos != null) {
                    try {
                        fos.close();
                    } catch (IOException ignored) {
                    }
                }
            }
        }
    }

    /**
     * 设置不验证主机
     */
    private static final HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    };

    /**
     * 信任所有
     *
     * @param connection
     * @return
     */
    private static SSLSocketFactory trustAllHosts(HttpsURLConnection connection) {
        SSLSocketFactory oldFactory = connection.getSSLSocketFactory();
        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            SSLSocketFactory newFactory = sc.getSocketFactory();
            connection.setSSLSocketFactory(newFactory);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return oldFactory;
    }

    /**
     * 覆盖java默认的证书验证
     */
    private static final TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[]{};
        }

        public void checkClientTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
        }
    }};


    /**
     * 安装APK文件
     */
    private void installApk() {
        File apkfile = getFile();
        if (!apkfile.exists()) {
            return;
        }
        // 通过Intent安装APK文件
        Intent intent = new Intent(Intent.ACTION_VIEW);
        Uri uri;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            ALog.e("chen", "需要provider安装");
            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            //第二个参数需要与<provider>标签中的android:authorities属性相同
            uri = FileProvider.getUriForFile(mContext, "com.ylkj.patient.fileprovider", apkfile);
        } else {
            ALog.e("chen", "正常安装");
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            uri = Uri.fromFile(apkfile);
        }
        intent.setDataAndType(uri, "application/vnd.android.package-archive");
        mContext.startActivity(intent);
    }

    File getFile() {
        int idx = mDownloadUrl.lastIndexOf("/");
        String name = mDownloadUrl.substring(idx + 1);
        File apkfile = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            ContextWrapper cw = new ContextWrapper(mContext);
            File directory = cw.getExternalFilesDir(Environment.MEDIA_MOUNTED);
            apkfile = new File(directory, name);
        } else {
            apkfile = new File(mSavePath, name);
        }

        return apkfile;
    }

    public interface UpgradeManagerListener {
        /**
         * 更新接口dismiss之后的回调 走更新弹窗消失之后的逻辑
         */
        void onUpgradeDismiss();
    }

    public enum UpdateFlag {
        /**
         * 更新的flag 官网、华为、小米、oppo、vivo
         */
        UN_UPDATE,
        UPDATE_FLAG_GUANWANG,
        UPDATE_FLAG_HUAWEI,
        UPDATE_FLAG_XIAOMI,
        UPDATE_FLAG_OPPO,
        UPDATE_FLAG_VIVO;
    }
}
